package com.coldlz.mmp.app;

import cn.hutool.core.io.FileUtil;
import com.coldlz.mmp.pojo.HttpRecord;
import com.coldlz.mmp.pojo.ProxyConfigVo;
import com.coldlz.mmp.pojo.Result;
import com.coldlz.mmp.pojo.TemplatePublisher;
import com.coldlz.mmp.proxy.MMPServer;
import com.coldlz.mmp.proxy.ProxyConfig;
import com.coldlz.mmp.proxy.SslContextManager;
import com.coldlz.mmp.proxy.SystemProxySetting;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.File;

@RestController
@RequestMapping("/settings")
public class SettingsController {
    public static final Logger log = LoggerFactory.getLogger(SettingsController.class);
    public final ProxyConfig proxyConfig;
    public final MMPServer server;
    private final TemplatePublisher<HttpRecord> templatePublisher;
    private final HttpRecordService httpRecordService;
    Flux<HttpRecord> flux;

    public SettingsController(HttpRecordService httpRecordService, TemplatePublisher<HttpRecord> templatePublisher) {
        this.httpRecordService = httpRecordService;
        this.proxyConfig = new ProxyConfig();
        this.proxyConfig.setRecorder(httpRecordService);
        this.server = new MMPServer(proxyConfig);
        this.templatePublisher = templatePublisher;
        this.flux = Flux.from(templatePublisher).cache(20);
    }

    @PostConstruct
    public void init() {
        SslContextManager.initLoad();
        start();
//        setOpenSystemProxy(true);
    }

    @ExceptionHandler
    public Result<String> exceptionHandler(Exception e) {
        log.error(getClass().getSimpleName() + " 发生异常", e);
        return Result.error(e.getMessage());
    }

    /*获取状态*/
    @GetMapping("/getConfig")
    public Result<ProxyConfigVo> getConfig() {
        ProxyConfigVo vo = new ProxyConfigVo();
        vo.setPort(proxyConfig.getPort());
        vo.setOpenSystemProxy(proxyConfig.isOpenSystemProxy());
        vo.setDirectForward(proxyConfig.getDirectForward());
        vo.setSystemcProxyOpened(proxyConfig.isSystemcProxyOpened());
        vo.setProxyStarted(server.started());
        return Result.ok(vo);
    }


    @PostMapping("/setPort")
    public Result<Object> setPort(int port) {
        proxyConfig.setPort(port);
        return Result.ok();
    }


    @PostMapping("/setOpenSystemProxy")
    public Result<Object> setOpenSystemProxy(@RequestParam Boolean openSystemProxy) {
        if (openSystemProxy) {
            // 开启系统代理
            int port = proxyConfig.getPort();
            SystemProxySetting.enableSystemProxy(port);
            proxyConfig.setSystemcProxyOpened(true);
        } else {
            // 关闭系统代理
            SystemProxySetting.resetSystemProxy();
            proxyConfig.setSystemcProxyOpened(false);
        }
        proxyConfig.setOpenSystemProxy(openSystemProxy);
        return Result.ok();
    }


    @PostMapping("/start")
    public Result<Object> start() {
        if (server.started()) {
            return Result.error("已经开启服务");
        }
        server.start();
        return Result.ok();
    }

    @PostMapping("/stop")
    public Result<Object> stop() {
        if (!server.started()) {
            return Result.error("服务未开启");
        }
        server.stop();
        return Result.ok();
    }


    @GetMapping(value = "/records", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<HttpRecord> records() {
        return flux;
    }


    @GetMapping("/record/viewResponseContent")
    public Mono<byte[]> viewResponseContent(Integer id, ServerWebExchange exchange) {
        return Mono.create(sink->{
            HttpRecord httpRecord = httpRecordService.getById(id);
            String contentType = httpRecord.getResponseContentType();
            String content = httpRecord.getResponseContent();
            if (contentType != null) {
                exchange.getResponse().getHeaders().add("Content-Type", contentType);
            }
            byte[] bytes = FileUtil.readBytes(new File(content));
            sink.success(bytes);
        });
    }

    @GetMapping("/record/viewRequestContent")
    public Mono<byte[]> viewRequestContent(Integer id, ServerWebExchange exchange) {
        return Mono.create(sink->{
            HttpRecord httpRecord = httpRecordService.getById(id);
            String contentType = httpRecord.getRequestContentType();
            String content = httpRecord.getRequestContent();
            if (contentType != null) {
                exchange.getResponse().getHeaders().add("Content-Type", contentType);
            }
            byte[] bytes = FileUtil.readBytes(new File(content));
            sink.success(bytes);
        });
    }
}
